// 从@follow/components/hooks/useMobile.js导入useMobile钩子，用于检测是否在移动设备上运行
import { useMobile } from "@follow/components/hooks/useMobile.js"
// 从@follow/components/ui/button导入Button和MotionButtonBase组件
// Button是标准按钮组件，MotionButtonBase是带动画效果的按钮基础组件
import { Button, MotionButtonBase } from "@follow/components/ui/button/index.js"
// 从@follow/components/ui/form导入表单相关组件
// Form是表单容器，FormControl是表单控件容器，FormField是表单字段，
// FormItem是表单项容器，FormLabel是表单标签，FormMessage是表单消息显示组件
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@follow/components/ui/form/index.jsx"
// 从@follow/components/ui/input导入Input组件，用于创建输入框
import { Input } from "@follow/components/ui/input/index.js"
// 从@follow/components/ui/segment导入SegmentGroup和SegmentItem组件
// 用于创建分段选择控件（类似标签页或单选按钮组）
import { SegmentGroup, SegmentItem } from "@follow/components/ui/segment/index.js"
// 从@follow/components/ui/select/responsive导入ResponsiveSelect组件
// 用于在移动设备上显示响应式选择器
import { ResponsiveSelect } from "@follow/components/ui/select/responsive.js"
import type { DiscoveryItem } from "@follow-app/client-sdk"
import { zodResolver } from "@hookform/resolvers/zod"
// 从@pkg导入repository信息，通常包含项目仓库信息
import { repository } from "@pkg"
// 从@tanstack/react-query导入useMutation钩子，用于处理数据修改操作
import { useMutation } from "@tanstack/react-query"
// 从immer导入produce函数，用于简化不可变数据更新操作
import { produce } from "immer"
// 从jotai导入atom和useAtomValue、useStore，用于状态管理
// atom用于创建状态原子，useAtomValue用于读取原子值，useStore用于获取状态存储实例
import { atom, useAtomValue, useStore } from "jotai"
import type { ChangeEvent, CompositionEvent } from "react"
import { startTransition, useCallback, useEffect } from "react"
import { useForm } from "react-hook-form"
// 从react-i18next导入useTranslation钩子，用于国际化处理
import { useTranslation } from "react-i18next"
// 从react-router导入useSearchParams钩子，用于处理URL查询参数
import { useSearchParams } from "react-router"
// 从zod导入z对象，用于数据验证和类型定义
import { z } from "zod"

// 从~/atoms/server-configs导入useIsInMASReview钩子，用于检查是否在MAS审查环境中
import { useIsInMASReview } from "~/atoms/server-configs"
// 从~/components/ui/modal/stacked/hooks导入useModalStack钩子，用于模态框管理
import { useModalStack } from "~/components/ui/modal/stacked/hooks"
import { followClient } from "~/lib/api-client"

// 从当前目录导入DiscoverFeedCard和FeedForm组件
import { DiscoverFeedCard } from "./DiscoverFeedCard"
import { FeedForm } from "./FeedForm"

const FEED_DISCOVERY_INFO = {
  search: {
    // 国际化标签键名
    label: "discover.any_url_or_keyword",
    schema: z.object({
      keyword: z.string().min(1),
      target: z.enum(["feeds", "lists"]),
    }),
  },
  // RSS类型配置
  rss: {
    // 国际化标签键名
    label: "discover.rss_url",
    // 默认值
    default: "https://",
    // URL前缀数组
    prefix: ["https://", "http://"],
    // 是否显示模态框
    showModal: true,
    // 标签后缀（显示Folo Flavored Feed规范链接）
    labelSuffix: (
      <a
        href={`${repository.url}/wiki/Folo-Flavored-Feed-Spec`}
        target="_blank"
        rel="noreferrer"
        className="text-accent border-accent inline-flex w-auto items-center gap-1 rounded-full border px-2 py-px text-sm font-normal"
      >
        <i className="i-mgc-book-6-cute-re" />
        <span>Folo Flavored Feed Spec</span>
      </a>
    ),
    schema: z.object({
      keyword: z.string().url().startsWith("https://"),
    }),
  },
  // RSSHub类型配置
  rsshub: {
    // 国际化标签键名
    label: "discover.rss_hub_route",
    // URL前缀数组
    prefix: ["rsshub://"],
    // 默认值
    default: "rsshub://",
    // 是否显示模态框
    showModal: true,
    // 标签后缀（显示RSSHub文档链接）
    labelSuffix: (
      <a
        href="https://docs.rsshub.app/"
        target="_blank"
        rel="noreferrer"
        className="text-accent border-accent inline-flex w-auto items-center gap-1 rounded-full border px-2 py-px text-sm font-normal"
      >
        <i className="i-mgc-book-6-cute-re" />
        <span>RSSHub Docs</span>
      </a>
    ),
    schema: z.object({
      keyword: z.string().url().startsWith("rsshub://"),
    }),
  },
} satisfies Record<
  string,
  {
    label: I18nKeys
    prefix?: string[]
    showModal?: boolean
    default?: string
    labelSuffix?: React.ReactNode
    schema?: any
  }
>

const discoverSearchDataAtom = atom<Record<string, DiscoveryItem[]>>()

// 导出DiscoverForm组件，接收type属性，默认为"search"
export function DiscoverForm({ type = "search" }: { type?: string }) {
  const {
    prefix,
    default: defaultValue,
    schema: formSchema,
    label,
    labelSuffix,
    showModal,
  } = FEED_DISCOVERY_INFO[type]!

  // 使用useSearchParams钩子获取和设置URL查询参数
  const [searchParams, setSearchParams] = useSearchParams()

  // 从查询参数中获取关键字，如果不存在则为空字符串
  const keywordFromSearch = searchParams.get("keyword") || ""

  // 使用useForm钩子初始化表单，传入验证解析器和默认值
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      keyword: defaultValue || keywordFromSearch || "",
      target: "feeds",
    },
    mode: "all",
  })

  // 从form对象中解构出watch和trigger函数
  // watch用于监听表单字段变化，trigger用于手动触发表单验证
  const { watch, trigger } = form

  // validate default value from search params
  useEffect(() => {
    // 如果没有来自搜索的关键字，则直接返回
    if (!keywordFromSearch) {
      return
    }
    // 触发keyword字段的验证
    trigger("keyword")
  }, [trigger, keywordFromSearch])

  // 使用watch监听target字段的变化
  const target = watch("target")

  // 构造atom的键名，由关键字和目标组成
  const atomKey = keywordFromSearch + target

  // 使用useTranslation钩子获取翻译函数
  const { t } = useTranslation()

  // 使用useIsInMASReview钩子检查是否在MAS审查环境中
  const isInMASReview = useIsInMASReview()

  // 使用useStore钩子获取jotai状态存储实例
  const jotaiStore = useStore()

  // 使用useMutation钩子创建搜索操作的mutation
  const mutation = useMutation({
    // 定义mutation函数，接收关键字和目标作为参数
    mutationFn: async ({ keyword, target }: { keyword: string; target: "feeds" | "lists" }) => {
      let { data } = await followClient.api.discover.discover({
        keyword: keyword.trim(),
        target,
      })

      // 如果在MAS审查环境中，过滤掉付费列表
      if (isInMASReview) {
        data = data.filter((item) => !item.list?.fee)
      }

      // 使用jotaiStore设置discoverSearchDataAtom的值
      // 使用immer的produce函数简化不可变更新操作
      jotaiStore.set(discoverSearchDataAtom, (prev) => ({
        ...prev,
        [atomKey]: data,
      }))

      // 返回搜索结果数据
      return data
    },
  })

  // 使用useAtomValue钩子获取当前atomKey对应的搜索数据，如果不存在则返回空数组
  const discoverSearchData = useAtomValue(discoverSearchDataAtom)?.[atomKey] || []

  // 使用useModalStack钩子获取模态框管理函数
  const { present, dismissAll } = useModalStack()

  // 定义表单提交处理函数
  function onSubmit(values: z.infer<typeof formSchema>) {
    if (FEED_DISCOVERY_INFO[type]!.showModal) {
      present({
        title: t("feed_form.add_feed"),
        content: () => <FeedForm url={values.keyword} onSuccess={dismissAll} />,
      })
    } else {
      // 否则执行搜索mutation
      mutation.mutate(values)
    }
  }

  const normalizeAndSet = useCallback(
    (rawValue: string) => {
      startTransition(() => {
        const trimmedKeyword = rawValue.trimStart()
        if (!prefix) {
          setValue(trimmedKeyword)
          return
        }
        const isValidPrefix = prefix.find((p) => trimmedKeyword.startsWith(p))
        if (!isValidPrefix) {
          setValue(prefix[0]!)
          return
        }
        if (trimmedKeyword.startsWith(`${isValidPrefix}${isValidPrefix}`)) {
          setValue(trimmedKeyword.slice(isValidPrefix.length))
          return
        }
        setValue(trimmedKeyword)

        function setValue(value: string) {
          form.setValue("keyword", value, { shouldValidate: true })
          syncKeyword(value)
        }

        function syncKeyword(keyword: string) {
          setSearchParams(
            (prev) => {
              const newParams = new URLSearchParams(prev)
              if (keyword) {
                newParams.set("keyword", keyword)
              } else {
                newParams.delete("keyword")
              }
              return newParams
            },
            {
              replace: true,
            },
          )
        }
      })
    },
    [form, prefix, setSearchParams],
  )

  const handleKeywordChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      const { value } = event.currentTarget
      // During composition, update raw value without normalization or syncing URL params
      if ((event.nativeEvent as InputEvent)?.isComposing) {
        form.setValue("keyword", value, { shouldValidate: false })
        return
      }
      normalizeAndSet(value)
    },
    [form, normalizeAndSet],
  )
  const handleCompositionEnd = useCallback(
    (event: CompositionEvent<HTMLInputElement>) => {
      normalizeAndSet(event.currentTarget.value)
    },
    [normalizeAndSet],
  )

  // 定义订阅成功处理函数，使用useCallback优化性能
  const handleSuccess = useCallback(
    (item: DiscoveryItem) => {
      const currentData = jotaiStore.get(discoverSearchDataAtom)
      // 如果没有当前数据则直接返回
      if (!currentData) return

      // 使用immer的produce函数更新状态
      jotaiStore.set(
        discoverSearchDataAtom,
        produce(currentData, (draft) => {
          // 查找对应的订阅项
          const sub = (draft[atomKey] || []).find((i) => {
            // 如果是feed类型，比较feed id
            if (item.feed) {
              return i.feed?.id === item.feed.id
            }
            // 如果是list类型，比较list id
            if (item.list) {
              return i.list?.id === item.list.id
            }
            // 其他情况返回false
            return false
          })

          // 如果没有找到对应的订阅项则直接返回
          if (!sub) return

          // 增加订阅计数，使用-~运算符确保结果至少为1
          sub.subscriptionCount = -~(sub.subscriptionCount as number)
        }),
      )
    },
    [atomKey, jotaiStore],
  )

  // 定义取消订阅处理函数，使用useCallback优化性能
  const handleUnSubscribed = useCallback(
    (item: DiscoveryItem) => {
      const currentData = jotaiStore.get(discoverSearchDataAtom)
      // 如果没有当前数据则直接返回
      if (!currentData) return

      // 使用immer的produce函数更新状态
      jotaiStore.set(
        discoverSearchDataAtom,
        produce(currentData, (draft) => {
          // 查找对应的订阅项
          const sub = (draft[atomKey] || []).find(
            (i) => i.feed?.id === item.feed?.id || i.list?.id === item.list?.id,
          )

          // 如果没有找到对应的订阅项则直接返回
          if (!sub) return

          // 减少订阅计数，如果当前值为NaN则设为0，否则减1
          sub.subscriptionCount = Number.isNaN(sub.subscriptionCount)
            ? 0
            : (sub.subscriptionCount as number) - 1
        }),
      )
    },
    [atomKey, jotaiStore],
  )

  // 定义目标变化处理函数，使用useCallback优化性能
  const handleTargetChange = useCallback(
    (value: string) => {
      // 设置表单target字段的值
      form.setValue("target", value as "feeds" | "lists")
    },
    [form],
  )

  // 使用useMobile钩子检测是否在移动设备上
  const isMobile = useMobile()

  // 返回JSX元素
  return (
    <>
      // 使用Form组件包装表单
      <Form {...form}>
        // 表单元素，绑定提交处理函数
        <form
          onSubmit={form.handleSubmit(onSubmit)}
          className="w-full max-w-[540px]"
          data-testid="discover-form"
        >
          // 表单内容区域，添加内边距
          <div className="p-5">
            // 使用FormField组件定义关键字字段
            <FormField
              control={form.control}
              name="keyword"
              render={({ field }) => (
                // FormItem定义表单项容器
                <FormItem className="mb-4">
                  // FormLabel定义表单标签
                  <FormLabel className="text-text text-headline mb-2 flex items-center gap-2 pl-2 font-bold">
                    {t(label)}
                    {labelSuffix}
                  </FormLabel>
                  // FormControl定义表单控件容器
                  <FormControl>
                    // Input组件作为输入框，绑定各种属性和事件处理函数
                    <Input
                      autoFocus
                      {...field}
                      onChange={handleKeywordChange}
                      onCompositionEnd={handleCompositionEnd}
                      placeholder={type === "search" ? "Enter URL or keyword..." : undefined}
                    />
                  </FormControl>
                  // FormMessage显示表单验证消息
                  <FormMessage />
                </FormItem>
              )}
            />
            // 如果是搜索类型，显示目标选择字段
            {type === "search" && (
              // 使用FormField组件定义目标字段
              <FormField
                control={form.control}
                name="target"
                render={({ field }) => (
                  // FormItem定义表单项容器
                  <FormItem className="mb-4 pl-2">
                    // 表单项头部，包含标签和控件
                    <div className="mb-2 flex items-center justify-between">
                      // FormLabel定义表单标签
                      <FormLabel className="text-text-secondary text-headline font-medium">
                        // 显示国际化标签
                        {t("discover.target.label")}
                      </FormLabel>
                      // FormControl定义表单控件容器
                      <FormControl>
                        // 控件容器
                        <div className="flex">
                          // 如果是移动设备，显示响应式选择器，否则显示分段选择控件
                          {isMobile ? (
                            <ResponsiveSelect
                              size="sm"
                              value={field.value}
                              onValueChange={handleTargetChange}
                              items={[
                                { label: t("discover.target.feeds"), value: "feeds" },
                                { label: t("discover.target.lists"), value: "lists" },
                              ]}
                            />
                          ) : (
                            <SegmentGroup
                              className="-mt-2 h-8"
                              value={field.value}
                              onValueChanged={handleTargetChange}
                            >
                              <SegmentItem value="feeds" label={t("discover.target.feeds")} />
                              <SegmentItem value="lists" label={t("discover.target.lists")} />
                            </SegmentGroup>
                          )}
                        </div>
                      </FormControl>
                    </div>
                    // FormMessage显示表单验证消息
                    <FormMessage />
                  </FormItem>
                )}
              />
            )}
            // 表单操作区域
            <div className="center flex" data-testid="discover-form-actions">
              // 提交按钮，根据表单验证状态和加载状态设置禁用和加载属性
              <Button
                disabled={!form.formState.isValid}
                type="submit"
                isLoading={mutation.isPending}
              >
                {showModal ? t("discover.preview") : t("words.search")}
              </Button>
            </div>
          </div>
        </form>
      </Form>
      // 搜索结果区域
      <div className="mt-8 w-full max-w-lg">
        // 如果搜索成功或有搜索数据，显示结果统计信息
        {(mutation.isSuccess || !!discoverSearchData?.length) && (
          <div className="mb-4 flex items-center gap-2 text-sm text-zinc-500">
            // 显示搜索结果数量
            {t("discover.search.results", { count: discoverSearchData?.length || 0 })}
            // 如果有搜索数据，显示清除按钮
            {discoverSearchData && discoverSearchData.length > 0 && (
              <MotionButtonBase
                className="hover:text-accent cursor-button flex items-center justify-between gap-2"
                type="button"
                onClick={() => {
                  // 清除当前搜索结果
                  jotaiStore.set(discoverSearchDataAtom, {
                    ...jotaiStore.get(discoverSearchDataAtom),
                    [atomKey]: [],
                  })
                  // 重置mutation状态
                  mutation.reset()
                }}
              >
                <i className="i-mgc-close-cute-re" />
              </MotionButtonBase>
            )}
          </div>
        )}
        // 搜索结果列表容器
        <div className="space-y-4 text-sm">
          // 遍历搜索数据，为每个项目渲染DiscoverFeedCard组件
          {discoverSearchData?.map((item) => (
            <DiscoverFeedCard
              key={item.feed?.id || item.list?.id}
              item={item}
              onSuccess={handleSuccess}
              onUnSubscribed={handleUnSubscribed}
              className="last:border-b-0"
            />
          ))}
        </div>
      </div>
    </>
  )
}
